from PyQt5.QtWidgets import QTableWidgetItem, QCheckBox, QLabel, QHBoxLayout, QWidget, QMenu, \
	QDialog, QMessageBox, QGraphicsOpacityEffect
from PyQt5.QtGui import QPixmap, QIcon
from PyQt5.QtCore import Qt, QPoint

from common.logger import logger
from common.retcode import RetCode
from common.utils import get_file_size_str
from api.folder import FolderAction

from windows.folder_name_edit import *
from windows.share import *
from windows.upload import *

class MainFilesTable():
	def __init__(self, main_win):
		self._main_win = main_win

		self._folder_name_edit_dlg = None
		self._share_dlg = None
		self._upload_dlg = None

		self._file_list = None
		self._path_list = None
		self._folder_cache = {}
		self._chboxes = []

		self._last_step = None
		self._file_list_to_opt = []
		self._path_list_to_opt = []

		self.initWidgets()

	def initWidgets(self):
		self._main_win.pushButtonUpload.clicked.connect(self.onClickedUpload)
		self._main_win.pushButtonDownload.clicked.connect(self.onClickedDownload)
		self._main_win.pushButtonCreateFolder.clicked.connect(self.onClickedCreateFolder)
		self._main_win.pushButtonDelete.clicked.connect(self.onClickedDelete)
		self._main_win.toolButtonBackToParentFolder.clicked.connect(self.onClickedBackToParentFolder)
		self._main_win.toolButtonRefreshFolder.clicked.connect(self.onClickedRefreshFolder)
		self.initMoreButtonActions()

		self._main_win.tableWidgetPersonalFiles.horizontalHeader().setFixedHeight(50) ##设置表头高度
		self._main_win.tableWidgetPersonalFiles.horizontalHeader().resizeSection(0, 50) #设置列的宽度
		self._main_win.tableWidgetPersonalFiles.horizontalHeader().resizeSection(1, 300) #设置列的宽度
		self._main_win.tableWidgetPersonalFiles.horizontalHeader().resizeSection(2, 150) #设置列的宽度
		self._main_win.tableWidgetPersonalFiles.horizontalHeader().resizeSection(3, 200) #设置列的宽度
		# self._main_win.tableWidgetPersonalFiles.horizontalHeader().resizeSection(3, 200) #设置列的宽度

		self._main_win.tableWidgetPersonalFiles.horizontalHeader().setSectionsClickable(False) #可以禁止点击表头的列

		self._main_win.tableWidgetPersonalFiles.setContextMenuPolicy(Qt.CustomContextMenu)  #允许右键产生子菜单
		self._main_win.tableWidgetPersonalFiles.customContextMenuRequested.connect(self.generateFileOptMenu)  #右键菜单

		self._main_win.tableWidgetPersonalFiles.itemSelectionChanged.connect(self.onPersonalFilesTableSelectionChanged) # 点选事件
		self._main_win.tableWidgetPersonalFiles.doubleClicked.connect(self.onDoubleClickedPersonalFilesTable) # 双击事件

	def initMoreButtonActions(self):
		menu = QMenu()
		self._main_win.pushButtonMoreActions.setMenu(menu)

		self._actionRename = menu.addAction('重命名')
		self._actionRename.setIconVisibleInMenu(False)
		self._actionRename.triggered.connect(self.onClickedRename)

		self._actionCopy = menu.addAction('拷贝副本')
		self._actionCopy.setIconVisibleInMenu(False)
		self._actionCopy.triggered.connect(self.onClickedCopy)

		self._actionCut = menu.addAction('剪切')
		self._actionCut.setIconVisibleInMenu(False)
		self._actionCut.triggered.connect(self.onClickedCut)

		self._actionPaste = menu.addAction('粘贴')
		self._actionPaste.setIconVisibleInMenu(False)
		self._actionPaste.triggered.connect(self.onClickedPaste)

		self._actionShare = menu.addAction('分享')
		self._actionShare.setIconVisibleInMenu(False)
		self._actionShare.triggered.connect(self.onClickedShare)

	########################################################################
	
	def onShowWindow(self):
		self.setFileOperationEnabled(False)
		self._actionPaste.setEnabled(False)
		self._folder_cache = {}
		self._chboxes = []

	def setFileOperationEnabled(self, is_enabled):
		self._actionRename.setEnabled(is_enabled)
		self._actionShare.setEnabled(is_enabled)

	########################################################################
	
	def getFolder(self, fid, forced=False):
		file_list = path_list = None
		if not forced and (fid in self._folder_cache):
			folder_info = self._folder_cache[fid]
			file_list, path_list = folder_info
		else:
			folder_action = FolderAction(self._main_win._sess_wp)
			file_list, path_list = folder_action.get_file_list(fid)
			print(f'file_list: {file_list}')
			print(f'path_list: {path_list}')
			self._folder_cache[fid] = (file_list, path_list)

		self._file_list = file_list
		self._path_list = path_list
		# 不位于根目录才能返回上一层
		self._main_win.toolButtonBackToParentFolder.setEnabled(len(path_list) > 1)

		self._main_win.tableWidgetPersonalFiles.setRowCount(len(file_list))
		row = 0
		self._chboxes = []
		for file_info in file_list:

			ckBox = QCheckBox()
			ckLayout = QHBoxLayout()
			ckLayout.setAlignment(Qt.AlignCenter)
			ckLayout.addWidget(ckBox)
			ckWidget = QWidget()
			ckWidget.setLayout(ckLayout)
			self._chboxes.append(ckBox)

			fileIconLabel = self._main_win.getFileIconLabel(file_info)

			fileNameLabel = QLabel()
			fileNameLabel.setText(file_info.name)
			fileNameLayout = QHBoxLayout()
			fileNameLayout.setAlignment(Qt.AlignLeft)
			fileNameLayout.addWidget(fileIconLabel)
			fileNameLayout.addWidget(fileNameLabel)
			fileNameWidget = QWidget()
			fileNameWidget.setLayout(fileNameLayout)


			sizeStr = ''
			if file_info.isFolder:
				if file_info.id > 0:
					sizeStr = '文件夹'
				else:
					sizeStr = '系统文件夹'
			else:
				sizeStr = get_file_size_str(file_info.size)
			sizeItem = QTableWidgetItem(sizeStr)
			sizeItem.setTextAlignment(Qt.AlignCenter)

			optimeItem = QTableWidgetItem(file_info.optime)
			optimeItem.setTextAlignment(Qt.AlignCenter)

			ctimeItem = QTableWidgetItem(file_info.ctime)
			ctimeItem.setTextAlignment(Qt.AlignCenter)

			self._main_win.tableWidgetPersonalFiles.setCellWidget(row, 0, ckWidget)
			self._main_win.tableWidgetPersonalFiles.setCellWidget(row, 1, fileNameWidget)
			self._main_win.tableWidgetPersonalFiles.setItem(row, 2, sizeItem)
			self._main_win.tableWidgetPersonalFiles.setItem(row, 3, optimeItem)
			self._main_win.tableWidgetPersonalFiles.setItem(row, 4, ctimeItem)

			row += 1

		cur_dir = ' > '.join(path_list.all_name)
		self._main_win.labelPathNavigator.setText(cur_dir)

	def generateFileOptMenu(self, pos):
		row_num = -1
		for idx in self._main_win.tableWidgetPersonalFiles.selectionModel().selection().indexes():
			row_num = idx.row()

		if row_num < 0:
			return

		if row_num >= len(self._file_list):
			return

		cur_file = self._file_list[row_num]

		menu = QMenu()
		item1 = None
		if cur_file.isFolder:
			item1 = menu.addAction(u"打开")
		item2 = menu.addAction(u"下载")
		item3 = menu.addAction(u"删除")
		item4 = menu.addAction(u"重命名")
		item5 = menu.addAction(u"拷贝副本")
		item6 = menu.addAction(u"剪切")
		item7 = menu.addAction(u"分享")
		action = menu.exec_(self._main_win.tableWidgetPersonalFiles.mapToGlobal(pos + QPoint(0, 30)))
		if action == item1:
			if cur_file.isFolder:
				self.getFolder(cur_file.id)
		elif action == item2:
			self.add_download_task(cur_file)
		elif action == item3:
			self.delFiles([cur_file])
		elif action == item4:
			path_info = self._path_list[-1]
			self.addFolderOrRename(cur_file.id, path_info.id, True, cur_file.name)
		elif action == item5:
			self.onClickedCopy()
		elif action == item6:
			self.onClickedCut()
		elif action == item7:
			self.onClickedShare()
		else:
			return

	def onClickedBackToParentFolder(self):
		if len(self._path_list) < 2:
			return
		path_info = self._path_list[-2]
		self.getFolder(path_info.id)

	def onClickedRefreshFolder(self):
		if len(self._path_list) < 1:
			return
		path_info = self._path_list[-1]
		self.getFolder(path_info.id, True)

	def onPersonalFilesTableSelectionChanged(self):
		items = self._main_win.tableWidgetPersonalFiles.selectedItems()
		if items and len(items) > 0:
			self.setFileOperationEnabled(True)
		else:
			self.setFileOperationEnabled(False)

	def onDoubleClickedPersonalFilesTable(self, mi):
		row_num = mi.row()
		# print(row_num)
		if row_num < 0:
			return

		if row_num >= len(self._file_list):
			return
		
		cur_file = self._file_list[row_num]
		if cur_file.isFolder: # 对于文件夹，双击执行打开
			self.getFolder(cur_file.id)

	########################################################################
	def getFilesSelected(self, chbox_included=True):
		files_sel = []
		rows_sel = set()
		row_num = 0
		if chbox_included:
			for chbox in self._chboxes:
				if chbox.isChecked():
					files_sel.append(self._file_list[row_num])
					rows_sel.add(row_num)
				row_num += 1
			if len(files_sel) > 0:
				return files_sel, rows_sel

		items = self._main_win.tableWidgetPersonalFiles.selectedItems()
		if items and len(items) > 0:
			files_sel.append(self._file_list[items[0].row()])
			rows_sel.add(items[0].row())

		return files_sel, rows_sel

	def onClickedUpload(self):
		if len(self._path_list) < 1:
			return
		path_info = self._path_list[-1]

		if not self._upload_dlg:
			self._upload_dlg = UploadDlg(self._main_win._transfer_table)
		self._upload_dlg.reset(path_info.id)
		self._upload_dlg.show()

	def onClickedDownload(self):
		cur_files, _ = self.getFilesSelected()
		if len(cur_files) <= 0:
			QMessageBox.information(self._main_win, "提示", "请先选择需要操作的文件/文件夹")
			return

		for file_info in cur_files:
			self.add_download_task(file_info)

	def onClickedCreateFolder(self):
		path_info = self._path_list[-1]
		self.addFolderOrRename(path_info.id, path_info.id)

	def addFolderOrRename(self, fid, reload_fid, is_rename=False, name=None):
		if not self._folder_name_edit_dlg:
			self._folder_name_edit_dlg = FolderNameEditDlg()

		self._folder_name_edit_dlg.reset(self._main_win._sess_wp, fid, is_rename, name)
		ret_code = self._folder_name_edit_dlg.exec_()
		# print(f'ret_code = {ret_code}')
		if ret_code == QDialog.Accepted:
			self.getFolder(reload_fid, True)

	def add_download_task(self, file_info):
		return self._main_win._transfer_table.add_download_task(file_info)

	def onClickedDelete(self):
		cur_files, _ = self.getFilesSelected()
		if len(cur_files) <= 0:
			QMessageBox.information(self._main_win, "提示", "请先选择需要操作的文件/文件夹")
			return
		self.delFiles(cur_files)

	def delFiles(self, file_infos):
		file_info = file_infos[0]
		file_cnt = len(file_infos)
		file_cnt_desc = f'等{file_cnt}个文件/文件夹' if file_cnt > 1 else ""
		file_type = '文件夹' if file_info.isFolder else '文件'
		
		msgBox = QMessageBox()
		msgBox.setWindowTitle('删除文件/文件夹')
		msgBox.setIcon(QMessageBox.Warning)
		icon = QIcon()
		icon.addPixmap(QPixmap(":/icon/icons/logo.png"), QIcon.Normal, QIcon.Off)
		msgBox.setWindowIcon(icon)
		msgBox.setText(f'确定要删除[{file_info.name}]{file_cnt_desc}吗？')
		btnOK = msgBox.addButton('确定', QMessageBox.AcceptRole)
		btnCancel = msgBox.addButton('取消', QMessageBox.RejectRole)
		msgBox.setDefaultButton(btnOK)
		reply = msgBox.exec()

		if reply != QMessageBox.AcceptRole:
			return
		for file_info in file_infos:
			logger.debug(f'删除文件：{file_type}[{file_info.name}] - {file_info.id}')
			folder_action = FolderAction(self._main_win._sess_wp)
			code = folder_action.delete_by_id(file_info.id)
			if code != RetCode.SUCCESS:
				QMessageBox.information(self._main_win, "提示", f"删除{file_type}[{file_info.name}]失败：{code}")
				return
		path_info = self._path_list[-1]
		self.getFolder(path_info.id, True)

	def onClickedRename(self):
		cur_files, _ = self.getFilesSelected(chbox_included=False)
		if len(cur_files) <= 0:
			QMessageBox.information(self._main_win, "提示", "请先选择需要操作的文件/文件夹")
			return
		cur_file = cur_files[0]
		path_info = self._path_list[-1]
		self.addFolderOrRename(cur_file.id, path_info.id, True, cur_file.name)

	def onClickedCopy(self):
		cur_files, _ = self.getFilesSelected()
		if len(cur_files) <= 0:
			QMessageBox.information(self._main_win, "提示", "请先选择需要操作的文件/文件夹")
			return
		
		folder_action = FolderAction(self._main_win._sess_wp)
		for file_info in cur_files:
			folder_action.copy_file(file_info.id)

		path_info = self._path_list[-1]
		self.getFolder(path_info.id, True)

	def	onClickedCut(self):
		cur_files, cur_rows = self.getFilesSelected()
		if len(cur_files) <= 0:
			QMessageBox.information(self._main_win, "提示", "请先选择需要操作的文件/文件夹")
			return

		for row in range(len(self._file_list)):
			cellWidget = self._main_win.tableWidgetPersonalFiles.cellWidget(row, 1)
			opacity_effect = QGraphicsOpacityEffect()
			if row in cur_rows:
				opacity_effect.setOpacity(0.3)
			else:
				opacity_effect.setOpacity(1)
			cellWidget.setGraphicsEffect(opacity_effect)

		self._last_step = 'cut'
		self._file_list_to_opt = cur_files
		self._path_list_to_opt = self._path_list
		self._actionPaste.setEnabled(True)

	def chkIfPasteValid(self):
		if self._last_step == 'cut' and self._path_list[-1].id == self._path_list_to_opt[-1].id:
			QMessageBox.information(self._main_win, "提示", "剪切到的目标文件夹必须与当前不同")
			return False

		for file_info in self._file_list_to_opt:
			if not file_info.isFolder:
				continue
			for path in self._path_list:
				if path.id == file_info.id:
					QMessageBox.information(self._main_win, "提示", "不可粘贴到被操作文件夹的子文件夹")
					return False

		return True


	def	onClickedPaste(self):
		if not self.chkIfPasteValid():
			return

		folder_action = FolderAction(self._main_win._sess_wp)
		path_info = self._path_list[-1]
		
		logger.info(f'{self._last_step} and paste {len(self._file_list_to_opt)} files to {path_info.id} start...')
		
		if self._last_step == 'cut':
			for file_info in self._file_list_to_opt:
				folder_action.move_file(file_info, path_info.id)

			org_path_info = self._path_list_to_opt[-1]
			if org_path_info.id in self._folder_cache:
				del self._folder_cache[org_path_info.id]

			self.getFolder(path_info.id, True)

		self._last_step = None
		self._file_list_to_opt = []
		self._path_list_to_opt = []
		self._actionPaste.setEnabled(False)

		logger.info('paste done')

	def onClickedShare(self):
		cur_files, _ = self.getFilesSelected(chbox_included=False)
		if len(cur_files) <= 0:
			QMessageBox.information(self._main_win, "提示", "请先选择需要操作的文件/文件夹")
			return
		cur_file = cur_files[0]

		if not self._share_dlg:
			self._share_dlg = ShareDlg()
		self._share_dlg.reset(self._main_win._sess_wp, cur_file)
		self._share_dlg.show()